package org.healthy.util;

import org.healthy.base.constant.RedisKeyConst;
import org.healthy.utils.pub.exception.ExceptionEnums;
import org.healthy.utils.pub.tool.SerializeUtil;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * redis 辅助操作类
 * Created by qingshengzheng on 15/11/18.
 */
public class JedisOper {

    private ShardedJedis shardedJedis;
    private ShardedJedisPool pool;
    private Boolean isAutoReturn = true;

    public JedisOper(ShardedJedis shardedJedis, ShardedJedisPool pool, Boolean isAutoReturn) {
        this.shardedJedis = shardedJedis;
        this.pool = pool;
        this.isAutoReturn = isAutoReturn;
    }

    public void returnResource() {
        pool.returnResource(shardedJedis);
    }

    public void returnResource(Boolean isAuto) {
        if (isAuto) returnResource();
    }

    public <T> T hget(String key, Object filed, Class<T> clazz) {
        byte[] bytes = shardedJedis.hget(key.getBytes(), filed.toString().getBytes());
        returnResource(isAutoReturn);
        if (bytes != null)
            return SerializeUtil.unserialize(bytes, clazz);
        return null;

    }

    public void lremstr(String key, Long count, String v) {
        shardedJedis.lrem(key, count, v);
        returnResource(isAutoReturn);
    }

    public void lrem(String key, Long count, Object o) {
        try {
            shardedJedis.lrem(key.getBytes("UTF-8"), count, SerializeUtil.serialize(o));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        returnResource(isAutoReturn);
    }

    public String lindexstr(String key, long index) {

        String s = shardedJedis.lindex(key, index);
        returnResource(isAutoReturn);
        return s;
    }

    public Long llen(String key) {
        Long len = shardedJedis.llen(key);
        returnResource(isAutoReturn);
        return len;
    }

    public Boolean hexist(String key, String field) {
        Boolean exists = shardedJedis.hexists(key, field);
        return exists;
    }


    public void hset(String key, Object field, Object o) {
        try {
            shardedJedis.hset(key.getBytes("UTF-8"), field.toString().getBytes("UTF-8"), SerializeUtil.serialize(o));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        returnResource(isAutoReturn);
    }

    public void hsetstr(String key, String field, String o) {
        shardedJedis.hset(key, field, o);
        returnResource(isAutoReturn);
    }

    public <T> List<T> zrevrange(String key, Object start, Object end, Class<T> clazz) {
        Set<byte[]> set = shardedJedis.zrevrange(key.getBytes(), Integer.parseInt(start.toString()), Integer.parseInt(end.toString()));
        returnResource(isAutoReturn);
        Iterator<byte[]> it = set.iterator();
        List<T> value = new ArrayList<T>();
        while (it.hasNext()) {
            T o = SerializeUtil.unserialize(it.next(), clazz);
            value.add(o);
        }
        return value;

    }

    public List<String> zrevrange(String key, Object start, Object end) {

        Set<String> set = shardedJedis.zrevrange(key, Long.parseLong(start.toString()), Long.parseLong(end.toString()));
        returnResource(isAutoReturn);
        List<String> v = new ArrayList<String>();
        v.addAll(set);
        return v;

    }


    public <T> List<T> zrevrangeByScore(String key, Object max, Object min, int offect, int count, Class<T> clazz) {

        Set<byte[]> set = shardedJedis.zrevrangeByScore(key.getBytes(), Long.parseLong(max.toString()), Long.parseLong(min.toString()), offect, count);
        returnResource(isAutoReturn);
        Iterator<byte[]> it = set.iterator();
        List<T> value = new ArrayList<T>();
        while (it.hasNext()) {
            T o = SerializeUtil.unserialize(it.next(), clazz);
            value.add(o);
        }
        return value;

    }

    public <T> List<T> zrangeByScore(String key, Object min, Object max, int offect, int count, Class<T> clazz) {
        Set<byte[]> set = shardedJedis.zrangeByScore(key.getBytes(), Long.parseLong(min.toString()), Long.parseLong(max.toString()), offect, count);
        returnResource(isAutoReturn);
        Iterator<byte[]> it = set.iterator();
        List<T> value = new ArrayList<T>();
        while (it.hasNext()) {
            T o = SerializeUtil.unserialize(it.next(), clazz);
            value.add(o);
        }
        return value;


    }


    public <T> List<T> zrevrangeByScore(String key, Object max, Object min, Long offect, Long count, Class<T> clazz) {
        return zrevrangeByScore(key, max.toString(), min, Integer.parseInt(offect.toString()), Integer.parseInt(count.toString()), clazz);
    }

    public void lpush(String key, Object... values) {
        byte[][] bytes = new byte[values.length][];
        for (int i = 0; i < values.length; i++) {
            bytes[i] = SerializeUtil.serialize(values[i]);
        }
        try {
            shardedJedis.lpush(key.getBytes("UTF-8"), bytes);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        returnResource(isAutoReturn);

    }

    public void lpushstr(String key, String value) {
        shardedJedis.lpush(key, value);
        returnResource(isAutoReturn);
    }

    public void rpushstr(String key, String value) {
        shardedJedis.rpush(key, value);
        returnResource(isAutoReturn);
    }

    public void lsetstr(String key, Long index, String value) {
        shardedJedis.lset(key, index, value);
        returnResource(isAutoReturn);
    }


    public List<String> zrevrangeByScore(String key, Object max, Object min, Integer offect, Integer count) {

        List<String> idarray = new ArrayList<String>();
        Set<String> ids = shardedJedis.zrevrangeByScore(key, Long.parseLong(max.toString()), Long.parseLong(min.toString()), offect, count);
        returnResource(isAutoReturn);
        idarray.addAll(ids);
        return idarray;

    }

    public List<String> zrevrangeByScore(String key, Object max, Object min, Long offect, Long count) {
        return zrevrangeByScore(key, max, min, Integer.parseInt(offect.toString()), Integer.parseInt(count.toString()));
    }


    public <T> List<T> hmget(String key, List<?> fileds, Class<T> clazz) {

        if (fileds == null || fileds.isEmpty()) return null;
        byte[][] bytes = new byte[fileds.size()][];
        for (int i = 0; i < fileds.size(); i++) {
            try {
                bytes[i] = fileds.get(i).toString().getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        List<byte[]> temp = shardedJedis.hmget(key.getBytes(), bytes);
        returnResource(isAutoReturn);
        Iterator<byte[]> it = temp.iterator();
        List<T> value = new ArrayList<T>();
        while (it.hasNext()) {
            T o = SerializeUtil.unserialize(it.next(), clazz);
            value.add(o);
        }
        return value;

    }

    public void zadd(String key, Object score, Object value) {
        shardedJedis.zadd(key.getBytes(), Long.parseLong(score.toString()), SerializeUtil.serialize(value));
        returnResource(isAutoReturn);
    }

    public void zaddstr(String key, Object score, String value) {
        shardedJedis.zadd(key, Long.parseLong(score.toString()), value);
        returnResource(isAutoReturn);
    }


    public void rpush(String key, Object value) {
        byte[] temp = SerializeUtil.serialize(value);
        try {
            shardedJedis.rpush(key.getBytes("UTF-8"), temp);
        } catch (Exception e) {
            e.printStackTrace();
            pool.returnResource(shardedJedis);

        } finally {
            returnResource(isAutoReturn);
        }
    }

    public void lpush(String key, Object value) {
        byte[] temp = SerializeUtil.serialize(value);
        try {
            shardedJedis.lpush(key.getBytes("UTF-8"), temp);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } finally {
            returnResource(isAutoReturn);
        }

    }

    public List<String> lrangestr(String key, long start, long stop) {
        List<String> v = shardedJedis.lrange(key, start, stop);
        returnResource(isAutoReturn);
        List<String> temp = new ArrayList<String>();
        if (v == null || v.size() == 0) return null;
        for (int i = 0; i < v.size(); i++) {
            if (v.get(i) != null) temp.add(v.get(i));
        }

        return temp;
    }


    public <T> List<T> lrange(String key, Object start, Object stop, Class<T> clazz) {
        List<byte[]> temp = null;
        try {
            temp = shardedJedis.lrange(key.getBytes("UTF-8"), Long.parseLong(start + ""), Long.parseLong(stop + ""));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        returnResource(isAutoReturn);
        if (temp == null || temp.size() == 0) return null;

        Iterator<byte[]> it = temp.iterator();
        List<T> value = new ArrayList<T>();
        while (it.hasNext()) {
            T o = SerializeUtil.unserialize(it.next(), clazz);
            if (o != null)
                value.add(o);
        }
        return value;
    }

    public void del(String key)

    {
        shardedJedis.del(key);
        returnResource(isAutoReturn);

    }

    public void hincrBy(String key, String field, Long v) {
        shardedJedis.hincrBy(key, field, v);
        returnResource(isAutoReturn);

    }

    public void zincrbystr(String key, Long score, String member) {
        shardedJedis.zincrby(key, score, member);
    }


    public void zincrby(String key, Long score, Object member) {
        try {
            shardedJedis.zincrby(key.getBytes("UTF-8"), Double.parseDouble(score.toString()), SerializeUtil.serialize(member));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        returnResource(isAutoReturn);
    }

    public void zrem(String key, String... member) {
        shardedJedis.zrem(key, member);
        returnResource(isAutoReturn);
    }


    public void ltrim(String key, Long start, Long stop) {
        shardedJedis.ltrim(key, start, stop);
        returnResource(isAutoReturn);
    }

    public List<String> hmget(String key, String... member) {
        List<String> v = shardedJedis.hmget(key, member);
        returnResource(isAutoReturn);
        return v;
    }

    public void set(String key, String value) {
        shardedJedis.set(key, value);
        returnResource(isAutoReturn);

    }

    public String get(String key) {
        String v = shardedJedis.get(key);
        returnResource(isAutoReturn);
        return v;
    }

    public void setex(String key, int seconds, String value) {
        shardedJedis.setex(key, seconds, value);
        returnResource(isAutoReturn);
    }

    public String hgetstr(String key, String field) {
        String v = shardedJedis.hget(key, field);
        returnResource(isAutoReturn);
        return v;
    }

    public Long zcount(String key, Long start, Long stop) {

        Long v = shardedJedis.zcount(key, start, stop);
        returnResource(isAutoReturn);
        return v;
    }

    public void zremrangeByRank(String key, Long start, Long stop) {
        shardedJedis.zremrangeByRank(key, start, stop);
        returnResource(isAutoReturn);
    }

    public void saddstr(String key, String... members) {
        shardedJedis.sadd(key, members);
        returnResource(isAutoReturn);

    }

    public void sremstr(String key, String... members) {
        shardedJedis.srem(key, members);
        returnResource(isAutoReturn);
    }


    public Boolean sismember(String key, String member) {
        Boolean is = shardedJedis.sismember(key, member);
        returnResource(isAutoReturn);
        return is;
    }

    public Long scard(String key) {
        Long count = shardedJedis.scard(key);
        returnResource(isAutoReturn);
        return count;

    }

    public void expire(String key,int seconds)
    {
        shardedJedis.expire(key,seconds);
        returnResource(isAutoReturn);

    }


}
